package com.zhu.day.log;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Slf4j
@Aspect
@Component
@EnableAspectJAutoProxy
public class LoggerAspect {

    //用于匹配当前执行方法持有指定注解的方法；
    @Pointcut("@annotation(com.zhu.day.log.LoggerPoint)")
    public void methodPointcut() {

    }

    //@within：用于匹配所以持有指定注解类型内的方法；
    @Pointcut("@within(com.zhu.day.log.LoggerPoint)")
    public void classPointcut() {
    }

    @Around("methodPointcut() || classPointcut() ")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object res;
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        String methodName = method.getName();
        Object[] args = joinPoint.getArgs();
        String jsonArgs = JSON.toJSONString(args);
        try {
            res = joinPoint.proceed(args);
            String jsonResult = JSON.toJSONString(res);
            if (StringUtils.isNotBlank(jsonResult) && jsonResult.length() > 2000) {
                jsonResult = jsonResult.substring(0, 2000);
            }
            log.info("LoggerAspect.method:{}, args:{}, result:{}, useTime:{}ms!", methodName, jsonArgs,
                    jsonResult, System.currentTimeMillis() - start);
            return res;
        } catch (Throwable throwable) {
            log.info("LoggerAspect.error.method:{}, args:{},error:{},useTime:{}ms", methodName, jsonArgs,
                    throwable.getClass(), System.currentTimeMillis() - start, throwable);
            throw throwable;
        }
    }

}
